package QueryService;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.thrift.TException;
import TopologyService.Topology;
import KVService.KVHandler;

import QueryService.QueryService.Iface;

public class QueryHandler implements Iface {

	// Member variables
    private Topology topology;
    private int ttl;
    KVHandler kvhandler;
	
    /**
     * Constructor for QueryHandler object.
     * 
     * @param topology the topology object
     * @param ttl the ttl for inserts and deletes
     * @param kvhandler the KV Service handler object
     * @throws TException 
     */
    public QueryHandler(Topology topology, int ttl, KVHandler kvhandler) {
    	this.topology = topology;
        this.ttl = ttl;
        this.kvhandler = kvhandler;    
    }
    
	@Override
	public List<String> getKeysContainingWord(String word,
											  Map<Integer, String> titlesMatching, 
											  int origin, 
											  int ttl) throws TException {
		
		System.out.println("Process " + topology.myID() + " searching for movie title: " + word);
		// List of strings to be returned
		List<String> matches = new ArrayList<String>();
		
		// Check if we are the origin node
		if (origin == topology.myID()) {
            // Message has made it around the ring, titlesMatching should be complete now
            System.out.println("Process " + topology.myID() + " returning: " + titlesMatching.size() + " matching movie titles.");
            
            // Build up the list of strings for the movie titles
    		for (String value : titlesMatching.values()) {
    			matches.add(value);
    		}
            
            // Return the list of strings for the movie titles
            return matches;
		}
		
		// This is the first call to this function, start the processing
		if (origin == -1) {
            // we are being called from the same node
            origin = topology.myID();
		}
		
		// If the TTL is still usable and we are not the origin node
		if (ttl > 0) 
		{			
			// Add our matching movie titles to the list
			try {
				ArrayList<Integer> keys = kvhandler.searchValues(word);
				for(int key :keys){
					String value = kvhandler.get(key);
					titlesMatching.put(key, value);
				}
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
			// Send updated key values along ring
			boolean sent = false;
			
			// While we have not sent
		    while (!sent)
		    {
		    	// Get the IP address and port of our next neighbor
		    	String ip = topology.getNextIP();
		    	int port = topology.getNextPort();
		 
		    	// Get the ID of the next neighbor
		    	int routedNode = topology.getNextID();
		    	
		    	// Try to send the message to the next node
				try 
				{	
					QueryClient nextQueryClient = new QueryClient(ip, port);
					System.out.println("Process " + topology.myID() + " sending matching titles to " + routedNode + " origin: " + origin);
					matches = nextQueryClient.getKeysContainingWord(word, titlesMatching, origin, ttl-1);
					sent = true;
					return matches;
				}
				catch (TException e) 
				{
					// Fix topology and try again
					topology.failureDetected(routedNode);
				}
		    }
		}
		else
		{
			System.out.println("Process " + topology.myID() + " killing getKeysContainingWord message ttl: " + ttl + " owner: " + (origin == topology.myID()));
		}
		
		return matches;
	}
	
}
